package Soul

import (
	codecs "sanguo/codec/cs"
	"sanguo/node/common/attr"
	"sanguo/node/common/com_type"
	"sanguo/node/common/transaction"
	"sanguo/node/node_game"
	"sanguo/node/node_game/module/role"
	"sanguo/node/node_game/user"
	table_GamePlay "sanguo/node/table/excel/table/GamePlay"
	table_SoulEnchant "sanguo/node/table/excel/table/SoulEnchant"
	cs_message "sanguo/protocol/cs/message"
	"time"

	"github.com/golang/protobuf/proto"
)

type transactionSoulUpLevel struct {
	transaction.TransactionBase
	user    *user.User
	req     *codecs.Message
	resp    *cs_message.SoulUpLevelToC
	errcode cs_message.EnumType
}

func (this *transactionSoulUpLevel) GetModuleName() string {
	return "Soul"
}

func (this *transactionSoulUpLevel) GetReplyMsg() proto.Message {
	return &cs_message.SoulUpLevelToC{}
}

func (this *transactionSoulUpLevel) SetExpiredTime(expired time.Time) {
	this.Expired = expired
}

func (this *transactionSoulUpLevel) GetExpiredTime() time.Time {
	return this.Expired
}

func (this *transactionSoulUpLevel) Begin() {

	this.resp = &cs_message.SoulUpLevelToC{}
	msg := this.req.GetData().(*cs_message.SoulUpLevelToS)

	roleModule := this.user.GetModuleByName("role").(*role.RoleModule)
	role := roleModule.CurrentRole()
	if role == nil || !role.IsRoleModleData() {
		node_game.Infoln(role.GetUserID(), "SoulUpLevel fail : role is nil")
		this.errcode = cs_message.EnumType_ERROR
		this.user.EndTrans(this)
		return
	}
	node_game.Infof("%s %d Call SoulUpLevel id:%d use:%v", role.GetUserID(), role.GetID(), msg.GetSoulId(), msg.GetUseProtection())

	//验证功能开启
	if role.GetLev() < table_GamePlay.Table_.IDMap[com_type.GamePaly_Soul].UnlockLevel {
		node_game.Infoln(role.GetUserID(), role.GetID(), "Soul System is not Unlock")
		this.errcode = cs_message.EnumType_ERROR
		this.user.EndTrans(this)
		return
	}

	soul := role.GetRoleSoul().GetSoul(msg.GetSoulId())
	isUse := msg.GetUseProtection()

	if soul == nil {
		node_game.Infoln(role.GetUserID(), role.GetID(), "SoulUpLevel fail:Soul is nil")
		this.errcode = cs_message.EnumType_ERROR
		this.user.EndTrans(this)
		return
	}

	SEDef := table_SoulEnchant.Table_.EnchantLevelMap[soul.EnchantLevel+1]
	if SEDef == nil {
		node_game.Infoln(role.GetUserID(), role.GetID(), "SoulUpLevel fail:SEDef is nil")
		this.errcode = cs_message.EnumType_ERROR
		this.user.EndTrans(this)
		return
	}

	gold, _ := role.GetRoleAttr().GetAttr(attr.Gold)
	gold -= int64(SEDef.GoldCost)
	if gold < 0 {
		node_game.Infoln(role.GetUserID(), role.GetID(), "SoulUpLevel fail :gold not enough")
		this.errcode = cs_message.EnumType_ERROR
		this.user.EndTrans(this)
		return
	}

	for _, v := range SEDef.ItemCost {
		if v.ItemId != 0 && v.ItemCount != 0 {
			item := role.GetRoleItem().GetItem(v.ItemId)
			if item == nil || item.ItemCount < v.ItemCount {
				node_game.Infoln(role.GetUserID(), role.GetID(), "SoulUpLevel fail:Costitem is nil or not enough")
				this.errcode = cs_message.EnumType_ERROR
				this.user.EndTrans(this)
				return
			}
		}
	}

	if isUse {
		if SEDef.ProtectionId != 0 && SEDef.ProtectionCount != 0 {
			item := role.GetRoleItem().GetItem(SEDef.ProtectionId)
			if item == nil {
				node_game.Infoln(role.GetUserID(), role.GetID(), "SoulUpLevel fail:Protection item is nil")
				this.errcode = cs_message.EnumType_ERROR
				this.user.EndTrans(this)
				return
			} else {
				if item.ItemCount < SEDef.ProtectionCount {
					node_game.Infoln(role.GetUserID(), role.GetID(), "SoulUpLevel fail:Protection itemCount is nil")
					this.errcode = cs_message.EnumType_ERROR
					this.user.EndTrans(this)
					return
				}
			}
		}
	}

	if role.GetRoleSoul().SoulUpLevel(soul, isUse) {
		this.resp.UpOk = proto.Int32(int32(1))
	} else {
		this.resp.UpOk = proto.Int32(int32(2))
	}

	//扣除消耗
	role.GetRoleAttr().SetAttr(attr.Gold, gold)
	for _, item := range SEDef.ItemCost {
		if item.ItemId != 0 && item.ItemCount != 0 {
			role.GetRoleItem().UseItem(item.ItemId, item.ItemCount)
		}
	}

	if isUse {
		if SEDef.ProtectionId != 0 && SEDef.ProtectionCount != 0 {
			role.GetRoleItem().UseItem(SEDef.ProtectionId, SEDef.ProtectionCount)
		}
	}

	//武魂为装备状态 重新计算战斗属性
	if role.GetRoleSoul().GetSoul(msg.GetSoulId()).IsEquip {
		role.TotalBattleAttr()
	}

	//发送背包变化
	role.OnSoulDirty()
	role.OnItemDirty()

	node_game.Infoln(role.GetUserID(), role.GetID(), "SoulUpLevel OK")
	this.errcode = cs_message.EnumType_OK
	this.user.EndTrans(this)
}

func (this *transactionSoulUpLevel) End() {
	this.resp.Errcode = cs_message.EnumType(this.errcode).Enum()
	this.user.Reply(this.req.GetSeriNo(), this.resp)
}

func (this *transactionSoulUpLevel) Timeout() {
	this.resp.Errcode = cs_message.EnumType(cs_message.EnumType_RETRY).Enum()
	this.user.EndTrans(this)
}

func init() {
	user.RegisterTransFunc(&cs_message.SoulUpLevelToS{}, func(user *user.User, msg *codecs.Message) transaction.Transaction {
		return &transactionSoulUpLevel{
			user: user,
			req:  msg,
		}
	})
}
